package transform

import (
	"crypto/sha1"
	"demo/domain/model"
	"demo/infra/common/constant"
	"demo/infra/common/utils"
	"demo/infra/middleware/cache"
	"encoding/hex"
	"net/http"
	"net/url"
	"strings"
	"time"

	"github.com/bytedance/gopkg/util/logger"
	"github.com/gin-gonic/gin"
	"github.com/mileusna/useragent"
)

type TransformMiddleware struct {
	cache          *cache.UrlMapCacheManager
	eventRecordRpo model.TransformEventRecordRepository
}

// NewTransformMiddleware 创建新的中间件
func NewTransformMiddleware(cache *cache.UrlMapCacheManager, eventRecordRpo model.TransformEventRecordRepository) *TransformMiddleware {
	return &TransformMiddleware{
		cache:          cache,
		eventRecordRpo: eventRecordRpo,
	}
}

// ExecuteMiddleware 执行中间件
func (middleware *TransformMiddleware) ExecuteMiddleware() gin.HandlersChain {
	return gin.HandlersChain{
		middleware.extractHeader(),
		middleware.urlTransform(),
		middleware.redirection(),
		middleware.recordEvent(),
	}
}

// extractHeader 提取请求头过滤器
func (middleware *TransformMiddleware) extractHeader() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 初始化上下文（存储在gin.Context中）
		ctx := &TransformContext{
			CompressCode:   c.Param("compressCode"),
			TransformEvent: &TransformEvent{},
			Headers:        make(map[string]string),
		}
		// 提取请求头
		for k, v := range c.Request.Header {
			if len(v) > 0 {
				ctx.Headers[k] = v[0]
			}
		}
		ctx.TransformEvent.ClientIp = utils.ExtractClientIp(c.Request)
		ctx.TransformEvent.UserAgent = c.Request.UserAgent()
		ctx.TransformEvent.CookieValue = c.Request.Header.Get("Cookie")
		c.Set("transformCtx", ctx)
		c.Next() // 执行下一个中间件
	}
}

// 短链转换
func (middleware *TransformMiddleware) urlTransform() gin.HandlerFunc {
	return func(c *gin.Context) {
		transformCtx := getTransformContext(c)
		if transformCtx == nil {
			c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "transform context not found"})
			return
		}
		compressCode := c.Param("code")
		transformCtx.CompressCode = compressCode
		transformCtx.TransformEvent.CompressCode = compressCode
		// 查询长链
		urlMap := middleware.cache.LoadUrlMapCacheByCompressCode(c, compressCode)
		if urlMap == nil {
			c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"error": "短链不存在"})
			return
		}
		transformCtx.TransformEvent.LongUrlString = urlMap.LongURL
		transformCtx.TransformEvent.ShortUrlString = urlMap.ShortURL
		transformCtx.TransformStatus = constant.TransformSuccess
		c.Next()
	}
}

// 重定向
func (middleware *TransformMiddleware) redirection() gin.HandlerFunc {
	return func(c *gin.Context) {
		transformCtx := getTransformContext(c)
		if transformCtx == nil || transformCtx.TransformStatus != constant.TransformSuccess {
			c.Next()
			return
		}
		// 执行重定向
		c.Redirect(http.StatusFound, transformCtx.TransformEvent.LongUrlString)
		transformCtx.TransformStatus = constant.RedirectionSuccess
		c.Next()
	}
}

// 记录转换记录
func (middleware *TransformMiddleware) recordEvent() gin.HandlerFunc {
	return func(c *gin.Context) {
		ctx, _ := c.Get("transformCtx")
		transformCtx := ctx.(*TransformContext)
		event := transformCtx.TransformEvent

		record := &model.TransformEventRecord{
			ClientIP:        event.ClientIp,
			ShortURL:        event.ShortUrlString,
			LongURL:         event.LongUrlString,
			CompressCode:    event.CompressCode,
			UserAgent:       event.UserAgent,
			RecordTime:      time.Now(),
			TransformStatus: transformCtx.TransformStatus.Value(),
		}
		// 生成唯一身份标识：SHA-1(客户端IP + '-' + UserAgent)
		uniqueIdentityStr := event.ClientIp + "-" + event.UserAgent
		sha1Hash := sha1.Sum([]byte(uniqueIdentityStr))
		record.UniqueIdentity = hex.EncodeToString(sha1Hash[:])

		// 生成短链和长链的摘要
		shortUrlHash := sha1.Sum([]byte(record.ShortURL))
		record.ShortURLDigest = hex.EncodeToString(shortUrlHash[:])

		longUrlHash := sha1.Sum([]byte(record.LongURL))
		record.LongURLDigest = hex.EncodeToString(longUrlHash[:])

		// 解析短链的查询参数
		if record.ShortURL != "" {
			parsedUrl, err := url.Parse(record.ShortURL)
			if err == nil && parsedUrl.RawQuery != "" {
				record.QueryParam = parsedUrl.RawQuery
			} else if err != nil {
				// 日志记录：解析URL异常
				logger.Warnf("解析短链查询参数异常, 事件内容: %+v, 错误: %v", record, err)
			}
		}
		// 解析User-Agent
		if event.UserAgent != "" {
			ua := useragent.Parse(event.UserAgent)
			// 处理操作系统信息
			osName := ua.OS
			osVersion := ua.OSVersion
			deviceType := ua.Device
			record.OSType = osName
			record.OSVersion = osVersion
			record.DeviceType = deviceType
			// 处理移动设备
			if strings.EqualFold(deviceType, "mobile") {
				// 提取手机类型和系统信息（模拟UserAgentUtils功能）
				systemType, systemVersion, phoneType := extractSystemInfo(ua)
				record.PhoneType = phoneType
				record.OSType = systemType
				record.OSVersion = systemVersion
			}
			// 处理浏览器信息
			record.BrowserType = ua.Name
			record.BrowserVersion = ua.Version
		}
		// 记录事件（异步）
		go middleware.eventRecordRpo.Save(c, record)
		c.Next()
	}

}

// 辅助函数：获取转换上下文
func getTransformContext(c *gin.Context) *TransformContext {
	val, exists := c.Get("transformCtx")
	if !exists {
		return nil
	}
	tc, ok := val.(*TransformContext)
	if !ok {
		return nil
	}
	return tc
}

// extractSystemInfo 提取系统类型、版本和手机类型（模拟Java的UserAgentUtils）
func extractSystemInfo(ua useragent.UserAgent) (systemType, systemVersion, phoneType string) {
	// 根据实际业务需求实现具体解析逻辑
	// 这里仅为示例，实际实现需根据User-Agent字符串提取详细信息
	systemType = ua.OS
	systemVersion = ua.OSVersion
	// 简单判断手机类型
	if strings.Contains(ua.String, "iPhone") {
		phoneType = "iPhone"
	} else if strings.Contains(ua.String, "Android") {
		phoneType = "Android"
	} else {
		phoneType = "Unknown"
	}
	return
}
